// ==================================================================================
// Shared Genomics Project MPI Codebase
// Version 1.0 30/04/2010
//
// (c) 2010 University of Manchester all rights reserved
//
// This file is distributed under the GNU General Public License, Version 2.  
// Please see the file COPYING.txt for more details
// ==================================================================================

/*!
\file
\brief Implementatin of Permutation Indices File 
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "copyfile.h"
#include "options.h"
#include "permfile.h"
#include "pmaths.h"
#include "suffixes.h"

// Size = nRows x nColumns
int permfile_create(struct selected_options *ops, int nRows, int nColumns) {
	int *values = NULL, i;
	FILE *fout = NULL;
	int bytes = sizeof(int) * nColumns;

	if (ops == NULL || nRows == 0 || nColumns == 0) 
		return 0;

	// Create the array for the results
	values = (int*) malloc(bytes);
	if (values == NULL) return 0;
	else {
		// Initialise the index array.
		for (i = 0; i < nColumns; i++) values[i] = i;
	}
	
	fout = fopen(ops->szPermFileName, "wb");
	if (fout == NULL) return 0;
	
	// Write the PERM sizes as the first 2 values.
	fwrite(&nRows, sizeof(nRows), 1, fout);
	fwrite(&nColumns, sizeof(nColumns), 1, fout);

	// Permute the index array.
	//for (i = 0; i < nColumns; i++) values[i] = i;
	for (i = 0; i < nRows; i++) {
		if(!permute(values, nColumns)) {
			if (values != NULL) free(values);
			if (fout != NULL) fclose(fout);
			return 0;
		} else {
			// Write the values to the permutation file.
			int j;
			for (j = 0; j < nColumns; j++) {
				fwrite(&(values[j]), sizeof(int), 1, fout);
			}
		}
	}

	if (values != NULL) free(values);
	if (fout != NULL) fclose(fout);

	return 1;
}

int* permfile_load(struct selected_options *ops, int *nRows, int *nColumns) {
	int *values = NULL;
	int nElements = 0;
	FILE *fin = NULL;

	if (ops == NULL || nRows == NULL || nColumns == NULL) return 0;
	fin = fopen(ops->szPermFileName, "rb");
	if (fin == NULL) return 0;

	// Read in row num ber, i.e. number of permutation.
	if(fread(nRows, sizeof(int), 1, fin) != 1) {
		if (fin != NULL) fclose(fin);
		return 0;
	}

	// Read in the column number, i.e. number of samples.
	if(fread(nColumns, sizeof(int), 1, fin) != 1) {
		if (fin != NULL) fclose(fin);
		return 0;
	}

	nElements = (*nColumns) * (*nRows);
	if (nElements == 0) {
		if (fin != NULL) fclose(fin);
		return 0;
	}
	
	// Allocate the memory.
	values = (int*) malloc(sizeof(int) * nElements);
	if (values == NULL) {
		if (fin != NULL) fclose(fin);
		return NULL;
	} else {
		int count = (int) fread(values, sizeof(int), nElements, fin);

		// Read an expected numbers of elements, PERM file not of expected dimensions therefore
		// flag an serious. This would be an serious error.
		if (count != nElements) {
			if (values != NULL) free(values);
			return NULL;
		}
	}
	if (fin != NULL) fclose(fin);

	return values;
}

int permfile_create_and_copy(struct selected_options *ops, int nRows, int nColumns, int rank) {
	BOOL jobDone = FALSE;
	char tmp_szRunId[TOKEN_LENGTH], remoteFilepath[FILE_PATH_LENGTH];

	if (ops == NULL) return 0;

	strcpy(tmp_szRunId, ops->szRunId);
	sprintf(ops->szRunId, "%s_%i", tmp_szRunId, rank);

	sprintf(ops->szPermFileName, "%s%s%s_%i", ops->ldir, ops->szRunId, SUFFIX_PERM_FILE, rank);
	sprintf(remoteFilepath, "%s%s%s", ops->rdir, tmp_szRunId, SUFFIX_PERM_FILE);

	if (permfile_create(ops, nRows, nColumns))  if (copyAndDeleteFile(ops->szPermFileName, remoteFilepath)) jobDone = TRUE;
	
	strcpy(ops->szRunId, tmp_szRunId); // Restore the original Run ID

	if (jobDone) return 1;
	else return 0;
}
